#ifndef RANDOMLIB_H
#define RANDOMLIB_H

#ifdef __cplusplus
extern "C" {
#endif

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>

typedef struct {
    uint32_t mt[624];
    int index;
} mt19937_state;

void mt19937Seed(mt19937_state* state, uint32_t seed);
double mt19937Next(mt19937_state* state);

typedef struct {
    uint64_t mt[312];  // 64位MT19937的状态数组大小是312
    int index;
} mt19937_64_state;

void mt19937_64Seed(mt19937_64_state* state, uint64_t seed);
double mt19937_64Next(mt19937_64_state* state);

typedef struct {
    uint32_t a;
} xorshift32_state;

void xorshift32Seed(xorshift32_state* state, uint32_t seed);
double xorshift32Next(xorshift32_state* state);

typedef struct {
    uint32_t state;
} lcg32_state;

void lcgSeed(lcg32_state* state, uint32_t seed);
double lcgNext(lcg32_state* state);

typedef struct {
    uint64_t state;
    uint64_t inc;
} pcg32_state;

void pcg32Seed(pcg32_state* state, uint32_t seed);
double pcg32Next(pcg32_state* state);

// 辅助函数

/**
 * @brief 生成[minn, maxn)范围内的均匀分布整数
 *
 * 将[0,1)均匀分布的随机数映射到指定整数范围[minn, maxn)。
 * 使用公式：result = minn + floor(n * (maxn - minn))
 *
 * @param n 各类随机数生成器生成的[0, 1)区间均匀分布数
 * @param minn 区间最小值（包含）
 * @param maxn 区间最大值（不包含）
 * @return 返回[minn, maxn)范围内的均匀分布整数
 * @note 要求maxn > minn，否则行为未定义
 */
int64_t randint(double n, int64_t minn, int64_t maxn);

/**
 * @brief 生成[minn, maxn)范围内的均匀分布浮点数
 *
 * 将[0,1)均匀分布的随机数线性映射到指定浮点数范围[minn, maxn)。
 * 使用公式：result = minn + n * (maxn - minn)
 *
 * @param n 各类随机数生成器生成的[0, 1)区间均匀分布数
 * @param minn 区间最小值（包含）
 * @param maxn 区间最大值（不包含）
 * @return 返回[minn, maxn)范围内的均匀分布浮点数
 * @note 要求maxn > minn，否则行为未定义
 */
double randfloat(double n, double minn, double maxn);

/**
 * @brief 根据概率生成随机布尔值
 *
 * 使用均匀分布的随机数n，根据指定的概率返回true或false。
 * 如果n < probability，返回true；否则返回false。
 *
 * @param n 各类随机数生成器生成的[0, 1)区间均匀分布数
 * @param probability 返回true的概率，应在[0, 1]范围内
 * @return 根据概率返回的布尔值
 * @note 如果probability ≤ 0，总是返回false；如果probability ≥ 1，总是返回true
 */
bool randbool(double n, double probability);

/**
 * @brief 生成正态分布（高斯分布）随机数
 *
 * 使用Box-Muller变换将两个均匀分布的随机数转换为正态分布随机数。
 * 使用公式：z0 = sqrt(-2.0 * log(n1)) * cos(2.0 * π * n2)
 *          result = mean + z0 * stddev
 *
 * @param n1 第一个[0,1)均匀分布随机数
 * @param n2 第二个[0,1)均匀分布随机数
 * @param mean 正态分布的均值
 * @param stddev 正态分布的标准差
 * @return 符合指定均值和标准差的正态分布随机数
 * @note 需要两个独立的均匀分布随机数作为输入
 */
double randnormal(double n1, double n2, double mean, double stddev);

/**
 * @brief 生成指数分布随机数
 *
 * 将均匀分布的随机数转换为指数分布随机数。
 * 使用逆变换法：result = -log(1 - n) / lambda
 *
 * @param n [0,1)均匀分布随机数
 * @param lambda 指数分布的率参数（正数）
 * @return 符合指数分布的随机数
 * @note lambda应为正数，否则行为未定义
 */
double randexponential(double n, double _lambda);

/**
 * @brief 随机打乱数组元素顺序
 *
 * 使用Fisher-Yates洗牌算法随机打乱数组元素的顺序。
 * 算法复杂度为O(n)，其中n是元素数量。
 *
 * @param eles 待打乱的数组指针
 * @param size_ele 单个元素的大小（字节数）
 * @param n_ele 数组中元素的数量
 * @param rng 随机数生成器函数，应返回[0,1)范围内的double值
 * @param state 传递给随机数生成器函数的状态参数
 *
 * @note 此函数会直接修改传入的数组
 * @note 随机数生成器函数应具有签名：double func(void* state)
 */
void shuffle(void* eles, size_t size_ele, size_t n_ele, double (*rng)(void* state), void* state);

/**
 * @brief 生成指定数量的随机字节
 *
 * @param output 输出缓冲区，必须至少有n_bytes大小
 * @param n_bytes 要生成的字节数
 * @param rng 随机数生成器函数，应返回[0,1)范围内的double值
 * @param state 传递给随机数生成器函数的状态参数
 */
void randbytes(uint8_t* output, size_t n_bytes,
                               double (*rng)(void* state), void* state);

#ifdef __cplusplus
}
#endif

#endif
